home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / slip / cslip-2.6 / libkvm / kvm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-19  |  6.9 KB  |  323 lines

  1. #ifndef lint
  2. static char rcsid[] =
  3.     "@(#) $Header: kvm.c,v 1.11 92/10/19 14:54:32 leres Exp $ (LBL)";
  4. #endif
  5. /*
  6.  * Copyright (c) 1990, 1991, 1992 Craig Leres
  7.  * Copyright (c) 1990, 1991, 1992 The Regents of the University of California.
  8.  * All rights reserved.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that: (1) source code distributions
  12.  * retain the above copyright notice and this paragraph in its entirety, (2)
  13.  * distributions including binary code include the above copyright notice and
  14.  * this paragraph in its entirety in the documentation or other materials
  15.  * provided with the distribution, and (3) all advertising materials mentioning
  16.  * features or use of this software display the following acknowledgement:
  17.  * ``This product includes software developed by the University of California,
  18.  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
  19.  * the University nor the names of its contributors may be used to endorse
  20.  * or promote products derived from this software without specific prior
  21.  * written permission.
  22.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  23.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  24.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  25.  */
  26.  
  27. /* BSD emulation of the SunOS 4 kvm_* routines */
  28.  
  29. #include <sys/param.h>
  30. #include <sys/types.h>
  31. #include <sys/vmmac.h>
  32. #include <sys/file.h>
  33.  
  34. #include <machine/pte.h>
  35.  
  36. #include <errno.h>
  37. #include <kvm.h>
  38. #include <nlist.h>
  39. #include <paths.h>
  40. #include <stdio.h>
  41.  
  42. #ifdef sun
  43. #define KERNBASE KERNELBASE
  44. #endif
  45.  
  46. static struct nlist nl_sys[] = {
  47. #ifdef sun
  48. /* Sun 3's just have to be different ... */
  49. #define N_SYSSIZE 0
  50.     { "_Syssize" },
  51. #define N_SYSMAP 1
  52.     { "_Sysmap" },
  53. #else
  54. #define N_SYSSIZE 0
  55.     { "_syssize" },
  56. #define N_SYSMAP 1
  57.     { "_sysmap" },
  58. #endif
  59.     { "" },
  60. };
  61.  
  62. extern char *malloc();
  63.  
  64. extern int errno;
  65. extern long lseek();
  66.  
  67. kvm_t *
  68. kvm_open(namelist, corefile, swapfile, flag, errstr)
  69.     char *namelist, *corefile, *swapfile;
  70.     int flag;
  71.     char *errstr;
  72. {
  73.     register int i;
  74.     register kvm_t *kd;
  75.     char *memfile;
  76.     int kflag;
  77.  
  78.     if ((kd = (kvm_t *)malloc(sizeof(kvm_t))) == 0) {
  79.         if (errstr != NULL)
  80.             fprintf(stderr, "%s: malloc failed\n", errstr);
  81.         return (NULL);
  82.     }
  83.     kd->k_vd = -1;
  84.     kd->k_kd = -1;
  85.     kd->k_md = -1;
  86.     kd->k_sd = -1;
  87.     kd->k_sysmap = NULL;
  88.     kd->k_prog = errstr;
  89.     if (namelist == NULL)
  90.         namelist = _PATH_UNIX;
  91.     memfile = NULL;
  92.     if (corefile == NULL) {
  93.         corefile = _PATH_KMEM;
  94.         memfile = _PATH_MEM;
  95.     }
  96.     if (swapfile == NULL)
  97.         swapfile = _PATH_DRUM;
  98.     kflag = (strcmp(namelist, _PATH_UNIX) != 0 ||
  99.         strcmp(corefile, _PATH_KMEM) != 0);
  100.     kd->k_namelist = namelist;
  101.  
  102.     if ((kd->k_vd = open(namelist, O_RDONLY)) < 0) {
  103.         i = errno;
  104.         if (kd->k_prog != NULL) {
  105.             fprintf(stderr, "%s: ", kd->k_prog);
  106.             perror(namelist);
  107.         }
  108.         (void)kvm_close(kd);
  109.         errno = i;
  110.         return (NULL);
  111.     }
  112.     if ((kd->k_kd = open(corefile, flag)) < 0) {
  113.         i = errno;
  114.         if (kd->k_prog != NULL) {
  115.             fprintf(stderr, "%s: ", kd->k_prog);
  116.             perror(corefile);
  117.         }
  118.         (void)kvm_close(kd);
  119.         errno = i;
  120.         return (NULL);
  121.     }
  122.     if (kflag) {
  123.         off_t off;
  124.         u_int size;
  125.  
  126.         if (kvm_nlist(kd, nl_sys) != 0) {
  127.             i = errno;
  128.             (void)kvm_close(kd);
  129.             errno = i;
  130.             return (NULL);
  131.         }
  132.         size = nl_sys[N_SYSSIZE].n_value * sizeof(struct pte);
  133.         kd->k_sysmap = (struct pte *)malloc(size);
  134.         if (kd->k_sysmap == 0) {
  135.             i = errno;
  136.             (void)kvm_close(kd);
  137.             if (kd->k_prog != NULL)
  138.                 fprintf(stderr, "%s: malloc failed (2)\n",
  139.                     kd->k_prog);
  140.             errno = i;
  141.             return (NULL);
  142.         }
  143.         off = nl_sys[N_SYSMAP].n_value - KERNBASE;
  144.         (void)lseek(kd->k_kd, off, L_SET);
  145.         (void)read(kd->k_kd, (char *)kd->k_sysmap, (int)size);
  146.     } else {
  147.         if ((kd->k_sd = open(swapfile, O_RDONLY)) < 0) {
  148.             if (kd->k_prog != NULL) {
  149.                 fprintf(stderr, "%s: ", kd->k_prog);
  150.                 perror(swapfile);
  151.             }
  152.             /* not fatal */
  153.         }
  154.         if (memfile && (kd->k_md = open(memfile, O_RDONLY)) < 0) {
  155.             if (kd->k_prog != NULL) {
  156.                 fprintf(stderr, "%s: ", kd->k_prog);
  157.                 perror(memfile);
  158.             }
  159.             /* not fatal */
  160.         }
  161.     }
  162.     return (kd);
  163. }
  164.  
  165. int
  166. kvm_close(kd)
  167.     register kvm_t *kd;
  168. {
  169.     register int stat;
  170.  
  171.     if (kd == NULL) {
  172.         errno = EBADF;
  173.         return (-1);
  174.     }
  175.     stat = 0;
  176.     if (kd->k_vd >= 0) {
  177.         stat |= close(kd->k_vd);
  178.         kd->k_vd = -1;
  179.     }
  180.     if (kd->k_kd >= 0) {
  181.         stat |= close(kd->k_kd);
  182.         kd->k_kd = -1;
  183.     }
  184.     if (kd->k_md >= 0) {
  185.         stat |= close(kd->k_md);
  186.         kd->k_md = -1;
  187.     }
  188.     if (kd->k_sd >= 0) {
  189.         stat |= close(kd->k_sd);
  190.         kd->k_sd = -1;
  191.     }
  192.     if (kd->k_sysmap) {
  193.         free(kd->k_sysmap);
  194.         kd->k_sysmap = 0;
  195.     }
  196.     free(kd);
  197.     return (stat);
  198. }
  199.  
  200. int
  201. kvm_read(kd, addr, buf, nbytes)
  202.     register kvm_t *kd;
  203.     register unsigned long addr;
  204.     register char *buf;
  205.     register unsigned nbytes;
  206. {
  207.     register int v;
  208.  
  209.     if (kd->k_sysmap) {
  210.         /* get kernel pte */
  211.         addr -= KERNBASE;
  212.         addr =
  213.             ctob(kd->k_sysmap[btop(addr)].pg_pfnum) + (addr & PGOFSET);
  214.     }
  215.     if ((v = lseek(kd->k_kd, addr, 0)) == -1)
  216.         return (v);
  217.     if ((v = read(kd->k_kd, buf, nbytes)) != nbytes)
  218.         return (-1);
  219.     return (v);
  220. }
  221.  
  222. int
  223. kvm_write(kd, addr, buf, nbytes)
  224.     register kvm_t *kd;
  225.     register unsigned long addr;
  226.     register char *buf;
  227.     register unsigned nbytes;
  228. {
  229.     register int v;
  230.  
  231.     if (kd->k_sysmap) {
  232.         /* get kernel pte */
  233.         addr -= KERNBASE;
  234.         addr =
  235.             ctob(kd->k_sysmap[btop(addr)].pg_pfnum) + (addr & PGOFSET);
  236.     }
  237.     if ((v = lseek(kd->k_kd, addr, 0)) == -1)
  238.         return (v);
  239.     if ((v = write(kd->k_kd, buf, nbytes)) != nbytes)
  240.         return (-1);
  241.     return (v);
  242. }
  243.  
  244. int
  245. kvm_nlist(kd, nl)
  246.     register kvm_t *kd;
  247.     register struct nlist *nl;
  248. {
  249.  
  250.     return (nlist(kd->k_namelist, nl));
  251. }
  252.  
  253. #include <sys/user.h>
  254. #include <sys/proc.h>
  255. #include <sys/vm.h>
  256.  
  257. /* Probably doesn't work for crash dumps */
  258. struct user *
  259. kvm_getu(kd, p)
  260.     register kvm_t *kd;
  261.     register struct proc *p;
  262. {
  263.     register struct pte *ptep;
  264.     register int i;
  265.     int size;
  266.     int nbytes, n;
  267.     register struct user *u;
  268.     register u_char *up;
  269.     struct pte pagetbl[UPAGES];
  270.     static union {
  271.         struct user user;
  272.         u_char buf[BLKDEV_IOSIZE];
  273.     } buf;
  274.  
  275.     u = &buf.user;
  276.     if ((p->p_flag & SLOAD) == 0) {
  277.         /* Process is swapped */
  278.         if (kd->k_sd < 0) {
  279.             errno = EBADF;
  280.             return (NULL);
  281.         }
  282.         (void) lseek(kd->k_sd, (long)dtob(p->p_swaddr), 0);
  283.         n = roundup(sizeof(*u), DEV_BSIZE);
  284.         if (read(kd->k_sd, u, n) == n)
  285.             return (u);
  286.         if (kd->k_prog != NULL) {
  287.             i = errno;
  288.             fprintf(stderr, "%s: kvm_getu swap: %s\n",
  289.                 kd->k_prog, strerror(i));
  290.             errno = i;
  291.         }
  292.         return (NULL);
  293.     }
  294.  
  295.     /* Process is in core */
  296.     if (kd->k_md < 0) {
  297.         errno = EBADF;
  298.         return (NULL);
  299.     }
  300.     ptep = pagetbl;
  301.     if (kvm_read(kd, p->p_addr, ptep, sizeof(pagetbl),
  302.         "user pt") != sizeof(pagetbl))
  303.         return (NULL);
  304.     up = buf.buf;
  305.     for (nbytes = sizeof(*u); nbytes > 0; ++ptep, nbytes -= NBPG) {
  306.         n = nbytes;
  307.         if (n > NBPG)
  308.             n = NBPG;
  309.         (void) lseek(kd->k_md, ptep->pg_pfnum * NBPG, 0);
  310.         if (read(kd->k_md, up, n) != n) {
  311.             if (kd->k_prog != NULL) {
  312.                 i = errno;
  313.                 fprintf(stderr, "%s: kvm_getu user pages: %s\n",
  314.                     kd->k_prog, strerror(i));
  315.                 errno = i;
  316.             }
  317.             return (NULL);
  318.         }
  319.         up += n;
  320.     }
  321.     return (u);
  322. }
  323.